#define BCCWIN
#define DOEXPORT
#include "nodavesimple.h"
#include "openSocket.h"
#include <Windows.h>
#include "plc_link.h"

//#include "interface.h"  
/*quote to interface.h will have conflict issue with datastruct.h*/
#pragma comment(lib, "libnodave.lib")

#define RACK		0
#define SLOT		1
#define PLC_PORT	102

_daveOSserialType fds;
daveInterface* di = NULL;
daveConnection* dc = NULL;

_daveOSserialType fds2;
daveInterface* di2 = NULL;
daveConnection* dc2 = NULL;

HANDLE plc_mutex = NULL;
HANDLE plc_mutex2 = NULL;
int connect_to_plc(char* ip)
{
	int result = FALSE;
	fds.rfd = openSocket(PLC_PORT, ip);
	fds.wfd = fds.rfd;
	if (fds.rfd != NULL) {
		//logdlg.log("open socket[%s:%d] OK.", ip, PLC_PORT);
		result = TRUE;
	}
	else {
		//log("open socket[%s:%d] Fail.", ip, PLC_PORT);
		//***********************
		result = FALSE;
	}

	if (result == TRUE) {
		di = daveNewInterface(fds, (char*)"myPLC", daveProtoMPI, daveProtoISOTCP, daveSpeed187k);
		int rt = daveInitAdapter(di);
		if (rt == 0) {
			dc = daveNewConnection(di, 2, RACK, SLOT);
			rt = daveConnectPLC(dc);
			if (rt == 0) {
				//logdlg.log("connected to PLC.");
				result = TRUE;
			}
			else {
				//logdlg.log("connect to PLC failed.");
				result = FALSE;
			}
		}
		else {
			//logdlg.log("init adapter fail.");
			result = FALSE;
		}
	}

	if (result == TRUE) {
		if (plc_mutex != NULL)
			delete plc_mutex;
		plc_mutex = CreateMutex(NULL, FALSE, L"plc_mutex");
	}

	return result;
}

int connect_to_plc2(char* ip)
{
	int result = FALSE;
	fds2.rfd = openSocket(PLC_PORT, ip);
	fds2.wfd = fds2.rfd;
	if (fds2.rfd != NULL) {
		//logdlg.log("open socket[%s:%d] OK.", ip, PLC_PORT);
		result = TRUE;
	}
	else {
		//log("open socket[%s:%d] Fail.", ip, PLC_PORT);
		//***********************
		result = FALSE;
	}

	if (result == TRUE) {
		di2 = daveNewInterface(fds2, (char*)"myPLC", daveProtoMPI, daveProtoISOTCP, daveSpeed187k);
		int rt = daveInitAdapter(di2);
		if (rt == 0) {
			dc2 = daveNewConnection(di2, 2, RACK, SLOT);
			rt = daveConnectPLC(dc2);
			if (rt == 0) {
				//logdlg.log("connected to PLC.");
				result = TRUE;
			}
			else {
				//logdlg.log("connect to PLC failed.");
				result = FALSE;
			}
		}
		else {
			//logdlg.log("init adapter fail.");
			result = FALSE;
		}
	}

	if (result == TRUE) {
		if (plc_mutex2 != NULL)
			delete plc_mutex2;
		plc_mutex2 = CreateMutex(NULL, FALSE, L"plc_mutex2");
	}

	return result;
}
int disconnect_from_plc()
{
	int result = FALSE;
	if (dc != NULL) {
		result = daveDisconnectPLC(dc);
		daveFree(dc);
		dc = NULL;
	}
	if (di != NULL) {
		result = daveDisconnectAdapter(di);
		daveFree(dc);
		di = NULL;
	}
	if (fds.rfd != NULL) {
		result = closeSocket(fds.rfd);
		fds.rfd = NULL;
	}

	return result;
}

int disconnect_from_plc2()
{
	int result = FALSE;
	if (dc2 != NULL) {
		result = daveDisconnectPLC(dc2);
		daveFree(dc2);
		dc2 = NULL;
	}
	if (di2 != NULL) {
		result = daveDisconnectAdapter(di2);
		daveFree(dc2);
		di2 = NULL;
	}
	if (fds2.rfd != NULL) {
		result = closeSocket(fds2.rfd);
		fds2.rfd = NULL;
	}

	return result;
}

int read_from_plc_db(int index, int start, int lens, BYTE* buf)
{
	//if (!IS_PLC_CONNECTED) {
	//	logdlg.log("Link to PLC Error!");
	//	return FALSE;
	//}
	WaitForSingleObject(plc_mutex, INFINITE);
	int result = 0;
	try
	{
		result = daveReadBytes(dc, daveDB, index, start, lens, buf);
	}
	catch (...)
	{
		//logdlg.log("read catch err.");
	}

	if (result != 0x00) {
		// 		char *mystr = NULL;
		// 		mystr = daveStrerror(result);
		//		log("read err:%s, index=%d, start=%d", mystr, index, start);
		//logdlg.log("read err.%d",result);
	}

	ReleaseMutex(plc_mutex);
	//Sleep(50);
	return result;
}

int read_from_plc_db2(int index, int start, int lens, BYTE* buf)
{
	//if (!IS_PLC_CONNECTED) {
	//	logdlg.log("Link to PLC Error!");
	//	return FALSE;
	//}
	WaitForSingleObject(plc_mutex2, INFINITE);
	int result = 0;
	try
	{
		result = daveReadBytes(dc2, daveDB, index, start, lens, buf);
	}
	catch (...)
	{
		//logdlg.log("read catch err.");
	}

	if (result != 0x00) {
		// 		char *mystr = NULL;
		// 		mystr = daveStrerror(result);
		//		log("read err:%s, index=%d, start=%d", mystr, index, start);
		//logdlg.log("read err.%d",result);
	}

	ReleaseMutex(plc_mutex2);
	//Sleep(50);
	return result;
}
int write_to_plc_db(int index, int start, int lens, void* buf)
{
	//if (!IS_PLC_CONNECTED) {
	//	logdlg.log("Link to PLC Error!");
	//	return FALSE;
	//}

	WaitForSingleObject(plc_mutex, INFINITE);
	int result = 0;
	BYTE* read = 0;

	try
	{
		result = daveWriteBytes(dc, daveDB, index, start, lens, buf);
	}
	catch (...)
	{
		//logdlg.log("write catch err.");
	}
	// 	result = read_from_plc_db(index, start, lens, read);
	// 	if (read != buf){
	// 		log("write err.%d,%d",&read,&buf);
	// 	}
	if (result != 0x00) {
		//logdlg.log("write err.%d", result);
	}
	ReleaseMutex(plc_mutex);
	//Sleep(50);
	return result;
}
int write_to_plc_db2(int index, int start, int lens, void* buf)
{
	//if (!IS_PLC_CONNECTED) {
	//	logdlg.log("Link to PLC Error!");
	//	return FALSE;
	//}

	WaitForSingleObject(plc_mutex2, INFINITE);
	int result = 0;
	BYTE* read = 0;

	try
	{
		result = daveWriteBytes(dc2, daveDB, index, start, lens, buf);
	}
	catch (...)
	{
		//logdlg.log("write catch err.");
	}
	// 	result = read_from_plc_db(index, start, lens, read);
	// 	if (read != buf){
	// 		log("write err.%d,%d",&read,&buf);
	// 	}
	if (result != 0x00) {
		//logdlg.log("write err.%d", result);
	}
	ReleaseMutex(plc_mutex2);
	//Sleep(50);
	return result;
}

std::string read_string(int index, int start)
{
	unsigned char buf[64]{ 0x00 };
	read_from_plc_db(index, start, 34, (BYTE*)buf);
	unsigned char strbuf[64]{ 0x00 };
	int i = 0;
	for (i = 0; i < buf[1]; i++)
	{
		if (buf[i + 2] == '\r' || buf[i + 2] == '\n' || buf[i + 2] == '\0') break;
		strbuf[i] = buf[i + 2];
	}
	return std::string((char*)strbuf, i); // Convert to std::string
}
